/* Water Utilities */

#include "TextureUtils.hlsl"

// Uv Offset Buffer
cbuffer UvOffsetBuffer : register(b2)
{
	float2	OffsetR;
	float2	OffsetG;
	float2	OffsetB;
	float2	OffsetA;
	float	WaterWidth;
	float	WaterHeight;
	float2	WaterPadding;
}

// Displacement Texture
Texture2D<float4> g_DisplacementTexture		: register(t0);
SamplerState g_DisplacementSampler			: register(s0);


// Calculate the Height
float4 CalculateHeight(float4 position)
{
	float2 uv = float2(0.0f, 0.0f);
	uv.x = (position.x + (WaterWidth / 2.0f)) / WaterWidth;
	uv.y = (position.z + (WaterHeight / 2.0f)) / WaterHeight;

	float baseLine = 4.0f;
	float r = MultiSampleTexture(g_DisplacementTexture, g_DisplacementSampler, uv + OffsetR, 0, float2(1.0f / WaterWidth, 1.0f / WaterHeight)).r * (baseLine * 2.0f);
	float g = MultiSampleTexture(g_DisplacementTexture, g_DisplacementSampler, uv + OffsetG, 0, float2(1.0f / WaterWidth, 1.0f / WaterHeight)).g * (baseLine * 4.0f);
	float b = MultiSampleTexture(g_DisplacementTexture, g_DisplacementSampler, uv + OffsetB, 0, float2(1.0f / WaterWidth, 1.0f / WaterHeight)).b * (baseLine * 8.0f);
	float a = MultiSampleTexture(g_DisplacementTexture, g_DisplacementSampler, uv + OffsetA, 0, float2(1.0f / WaterWidth, 1.0f / WaterHeight)).a * (baseLine * 16.0f);
	float sampleVal = (r + g + b + a);

	position.y += sampleVal;

	return position;
}

// Apply the Shader to a Vertex
float3 CalculateNormal(float4 p, float2 d)
{
	float4 left = float4(p.x - d.x, p.y, p.z, p.w);
	float4 right = float4(p.x + d.x, p.y, p.z, p.w);
	float4 top = float4(p.x, p.y, p.z + d.y, p.w);
	float4 bottom = float4(p.x, p.y, p.z - d.y, p.w);

	left = CalculateHeight(left);
	right = CalculateHeight(right);
	top = CalculateHeight(top);
	bottom = CalculateHeight(bottom);

	float3 n = float3(0.0f, 0.0f, 0.0f);
	uint c = 0;

	float3 aa = normalize(left - p).xyz;
	float3 ab = normalize(bottom - p).xyz;
	n += normalize(cross(ab, aa));
	++c;

	float3 ba = normalize(bottom - p).xyz;
	float3 bb = normalize(right - p).xyz;
	n += normalize(cross(bb, ba));
	++c;

	float3 ca = normalize(right - p).xyz;
	float3 cb = normalize(top - p).xyz;
	n += normalize(cross(cb, ca));
	++c;


	float3 da = normalize(top - p).xyz;
	float3 db = normalize(left - p).xyz;
	n += normalize(cross(db, da));
	++c;

	n /= c;
	n = normalize(n);

	return n;
}